This document provides a comprehensive guide for migrating from the C++ Qt implementation to the C# .NET 8 implementation of QR Generator.
| Feature | C++ Qt | C# .NET 8 |
|---|---|---|
| WiFi Password Encryption | XOR with salt | AES-256-GCM |
| Key Derivation | SHA-256 (1000 rounds) | PBKDF2 (100,000 rounds) |
| Authentication | None | AEAD with GCM tag |
| Tamper Detection | ❌ No | ✅ Yes |
| Security Level | ✅ Military-grade |
- Dependency Injection: Proper IoC container
- MVVM Pattern: Clean separation of concerns
- Async/Await: Better async handling
- Modern UI: Material Design 3
- Testing: 90+ comprehensive unit tests
- Logging: Structured logging with Serilog
# Install .NET 8 SDK
# https://dotnet.microsoft.com/download/dotnet/8.0
# Verify installation
dotnet --version # Should show 8.0.x# Linux (C++ version data)
cp -r ~/.config/QRGenerator ~/QRGenerator_backup
# Windows (both versions)
xcopy "%APPDATA%\QRGenerator" "%APPDATA%\QRGenerator_backup" /E /IIf you have saved WiFi networks in the C++ version, you need to manually re-enter them in the C# version due to encryption changes.
Why? C++ uses XOR encryption, C# uses AES-256-GCM (incompatible formats).
How to migrate:
- Open C++ version
- For each saved network:
- Load the network
- Note down SSID, password, security type
- Open C# version
- Re-add networks with same credentials
Automated migration script (PowerShell):
# Note: This requires decrypting C++ passwords first
# C++ passwords are encrypted with XOR - you'll need to decrypt manually
$cppData = Get-Content "$env:APPDATA\QRGenerator\wifi_networks.json" | ConvertFrom-Json
foreach ($network in $cppData.networks) {
Write-Host "Network: $($network.ssid)"
Write-Host "Security: $($network.security)"
Write-Host "You need to manually enter the password in C# version"
Write-Host "---"
}# Clone/pull latest version
cd QR_Generator
git pull
# Navigate to .NET solution
cd dotnet
# Restore dependencies
dotnet restore
# Build
dotnet build --configuration Release
# Run
dotnet run --project QRGenerator.WPF- Test QR code generation (Text, URL, Contact, WiFi)
- Test QR code reading
- Save a WiFi network
- Load a WiFi network
- Export QR code to file
- Copy QR code to clipboard
C++ (XOR):
// Pseudo-code
salt = random_bytes(16)
key = sha256(machine_id + secret)
encrypted = plaintext XOR key
output = salt + encrypted // Base64C# (AES-256-GCM):
// Actual implementation
salt = RandomNumberGenerator.GetBytes(16);
nonce = RandomNumberGenerator.GetBytes(12);
key = PBKDF2(masterKey, salt, 100000 iterations);
encrypted = AES-GCM.Encrypt(plaintext, key, nonce);
tag = GCM authentication tag;
output = salt + nonce + tag + encrypted; // Base64| Attack Vector | C++ XOR | C# AES-GCM |
|---|---|---|
| Known-plaintext | ✅ Secure | |
| Chosen-plaintext | ✅ Secure | |
| Tampering | ✅ Detected | |
| Brute-force | ✅ Slow (PBKDF2) | |
| Replay attacks | ✅ Prevented (nonce) |
- Security: XOR is cryptographically weak
- Compatibility: Cannot securely decrypt XOR without the exact implementation
- Best Practice: Fresh encryption with strong algorithm
Recommendation: Re-enter WiFi passwords in C# version for maximum security.
C++ Qt:
class MyWidget : public QWidget {
Q_OBJECT
public:
MyWidget(QWidget* parent = nullptr);
private:
QLabel* label;
QPushButton* button;
private slots:
void onButtonClicked();
};C# WPF:
<!-- MyControl.xaml -->
<UserControl x:Class="MyApp.MyControl">
<StackPanel>
<TextBlock x:Name="label" Text="Hello"/>
<Button Content="Click Me" Click="OnButtonClicked"/>
</StackPanel>
</UserControl>// MyControl.xaml.cs
public partial class MyControl : UserControl
{
public MyControl()
{
InitializeComponent();
}
private void OnButtonClicked(object sender, RoutedEventArgs e)
{
label.Text = "Clicked!";
}
}C++ Qt:
connect(button, &QPushButton::clicked, this, &MyClass::onButtonClicked);C# WPF (Event):
button.Click += OnButtonClicked;C# WPF (MVVM Command):
// ViewModel
[RelayCommand]
private void OnButtonClick()
{
// Handle click
}<!-- View -->
<Button Command="{Binding OnButtonClickCommand}" Content="Click Me"/>C++ Qt:
Q_LOGGING_CATEGORY(qrgen_crypto, "qrgenerator.crypto")
qCInfo(qrgen_crypto) << "Encryption started";
qCWarning(qrgen_crypto) << "Weak password detected";C# .NET:
private readonly ILogger<MyService> _logger;
_logger.LogInformation("Encryption started");
_logger.LogWarning("Weak password detected");C++ Qt:
QByteArray data = qrCode->generate("Hello");
QString base64 = data.toBase64();C# .NET:
byte[] data = qrCodeService.GenerateQRCode("Hello");
string base64 = Convert.ToBase64String(data);C++ Qt:
QString text = "Hello";
QString upper = text.toUpper();
bool contains = text.contains("ell");C# .NET:
string text = "Hello";
string upper = text.ToUpper();
bool contains = text.Contains("ell");C++ Qt:
QSettings settings("QRGenerator", "WiFi");
settings.setValue("network/ssid", "MyNetwork");
QString ssid = settings.value("network/ssid").toString();C# .NET:
// Using JSON serialization
var data = new { Ssid = "MyNetwork" };
var json = JsonSerializer.Serialize(data);
var path = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"QRGenerator", "settings.json");
File.WriteAllText(path, json);
// Reading
var jsonRead = File.ReadAllText(path);
var dataRead = JsonSerializer.Deserialize<dynamic>(jsonRead);C++ Qt:
std::unique_ptr<QRcode> qrCode(QRcode_encodeString(...));
// Automatic cleanup on scope exitC# .NET:
// Garbage collector handles cleanup automatically
var qrCode = new QRCodeGenerator();
// No need for manual cleanup (unless implementing IDisposable)
// For IDisposable objects
using (var stream = new FileStream("file.txt", FileMode.Open))
{
// Automatic disposal
}- ✅ Text QR code generation
- ✅ URL QR code generation
- ✅ vCard (Contact) QR code generation
- ✅ WiFi QR code generation
- ✅ QR code reading from files
- ✅ QR code type detection
- ✅ WiFi network management (save/load/delete)
- ✅ AES-256-GCM encryption
- ✅ Material Design UI
- ✅ Error correction levels (L, M, Q, H)
- ✅ Adjustable QR code size
- ✅ Save QR codes to file (PNG, JPG, BMP)
- ✅ Copy QR codes to clipboard
- ✅ Comprehensive unit tests
- ✅ Structured logging
- ⏳ Camera QR code scanning (C++ had OpenCV camera support)
- ⏳ Internationalization (Polish/English) - UI is currently English-only
- ⏳ Batch QR generation
- ⏳ QR code customization (colors, logos)
- ⏳ Cross-platform support (Linux/macOS via .NET MAUI)
Cause: Encryption algorithm changed (XOR → AES-256-GCM)
Workaround: Manually re-enter WiFi networks in C# version
Future Fix: Migration tool to decrypt C++ XOR and re-encrypt with AES-GCM
Cause: ZXing.Net camera support requires additional implementation
Workaround: Use QR code reading from file
Future Fix: Implement Emgu.CV camera capture
Cause: WPF is Windows-specific
Workaround: Run on Windows 10/11
Future Fix: Migrate to .NET MAUI for cross-platform support
| Component | C++ Qt Tests | C# .NET Tests |
|---|---|---|
| Validation | ✅ 20 tests | ✅ Integrated in services |
| Encryption | ✅ 10 tests | ✅ 20+ tests |
| QR Generation | ❌ None | ✅ 25+ tests |
| QR Reading | ❌ None | ✅ 20+ tests |
| WiFi Management | ❌ None | ✅ 25+ tests |
| Total | ~30 tests | 90+ tests |
| Operation | C++ Qt | C# .NET 8 | Winner |
|---|---|---|---|
| Generate Text QR | ~12ms | ~15ms | C++ (20% faster) |
| Encrypt Password (XOR) | ~2ms | - | N/A |
| Encrypt Password (AES) | - | ~80ms | N/A (different algorithms) |
| Read QR from file | ~45ms | ~50ms | C++ (10% faster) |
| Startup Time | ~400ms | ~800ms | C++ (2x faster) |
| Memory Usage | ~50MB | ~80MB | C++ (40% less) |
Verdict: C++ is slightly faster, but C# provides better security and maintainability.
- Backup all data from C++ version
- Export list of saved WiFi networks (SSIDs and passwords)
- Test all features in C++ version one last time
- Take screenshots of any custom configurations
- Install .NET 8 SDK
- Clone/pull latest C# code
- Build and run C# version
- Verify UI works correctly
- Re-enter WiFi networks
- Test QR generation for all types
- Test QR reading
- Verify all WiFi networks work
- Test encryption/decryption
- Compare QR codes between C++ and C# (should be identical)
- Run unit tests (
dotnet test) - Check logs for any errors
- Keep C++ version as backup for 1 month
Cause: You're trying to use C++ encrypted passwords in C# version.
Solution: Re-enter passwords manually in C# version.
Cause: .NET runtime initialization overhead.
Solution: This is normal. Subsequent operations are fast.
Cause: Some features not yet implemented in C# (e.g., camera scanning).
Solution: Check Feature Parity section. Use C++ version for missing features or wait for implementation.
If you encounter issues during migration:
- Check this migration guide
- Review README_DOTNET.md for C# usage
- Check Issues for similar problems
- Create a new issue with:
- C++ version used
- Migration step where issue occurred
- Error messages/screenshots
Recommended: Migrate to C# version for better security.
Keep C++ version if:
- You need camera QR scanning
- You need Linux/macOS support
- C# version missing critical feature
Recommended: Develop new features in C# version.
Contribute to C++ if:
- Cross-platform support is critical
- Performance is top priority
Happy Migration! 🚀
Document created: 2025-11-18 Version: 1.0 C++ Qt 6.x → C# .NET 8