frontendPlayer/lib/data/services/video_encryptor_stub.dart
2026-04-10 09:55:19 +03:30

100 lines
2.9 KiB
Dart

import 'dart:typed_data';
import 'dart:math';
import 'package:pointycastle/export.dart';
class EncryptedVideoPayload {
final Uint8List encryptedFileBytes;
final String contentId;
final String contentKeyHex;
final String encryptedFileName;
EncryptedVideoPayload({
required this.encryptedFileBytes,
required this.contentId,
required this.contentKeyHex,
required this.encryptedFileName,
});
}
Future<EncryptedVideoPayload> encryptVideoForUpload(
Uint8List sourceBytes,
) async {
final random = Random.secure();
final keyBytes = Uint8List.fromList(
List<int>.generate(16, (_) => random.nextInt(256)),
);
final nonceBytes = Uint8List.fromList(
List<int>.generate(8, (_) => random.nextInt(256)),
);
final contentId = _generateUuidV4(random);
final contentIdBytes = _uuidToBytes(contentId);
final contentKeyHex = _bytesToHex(keyBytes);
final counterBlock = Uint8List(16);
counterBlock.setRange(0, nonceBytes.length, nonceBytes);
final cipher = CTRStreamCipher(AESEngine())
..init(
true,
ParametersWithIV<KeyParameter>(KeyParameter(keyBytes), counterBlock),
);
final encryptedData = cipher.process(sourceBytes);
final magic = Uint8List.fromList('MYPLR1'.codeUnits);
const version = 1;
final headerSize = magic.length + 1 + contentIdBytes.length + nonceBytes.length;
final finalBytes = Uint8List(headerSize + encryptedData.length);
var offset = 0;
finalBytes.setRange(offset, offset + magic.length, magic);
offset += magic.length;
finalBytes[offset] = version;
offset += 1;
finalBytes.setRange(offset, offset + contentIdBytes.length, contentIdBytes);
offset += contentIdBytes.length;
finalBytes.setRange(offset, offset + nonceBytes.length, nonceBytes);
offset += nonceBytes.length;
finalBytes.setRange(offset, offset + encryptedData.length, encryptedData);
return EncryptedVideoPayload(
encryptedFileBytes: finalBytes,
contentId: contentId,
contentKeyHex: contentKeyHex,
encryptedFileName: '$contentId.spot',
);
}
String _bytesToHex(Uint8List bytes) {
final buffer = StringBuffer();
for (final byte in bytes) {
buffer.write(byte.toRadixString(16).padLeft(2, '0'));
}
return buffer.toString();
}
Uint8List _uuidToBytes(String uuid) {
final hex = uuid.replaceAll('-', '');
final output = Uint8List(16);
for (var i = 0; i < 16; i++) {
output[i] = int.parse(hex.substring(i * 2, i * 2 + 2), radix: 16);
}
return output;
}
String _generateUuidV4(Random random) {
final bytes = List<int>.generate(16, (_) => random.nextInt(256));
bytes[6] = (bytes[6] & 0x0f) | 0x40;
bytes[8] = (bytes[8] & 0x3f) | 0x80;
final hex = bytes
.map((b) => b.toRadixString(16).padLeft(2, '0'))
.join();
return '${hex.substring(0, 8)}-'
'${hex.substring(8, 12)}-'
'${hex.substring(12, 16)}-'
'${hex.substring(16, 20)}-'
'${hex.substring(20, 32)}';
}