Fix: Currency display consistency and remove PGP security vulnerability

## Critical Bug Fixes

### Currency Display (£ vs $)
- Fix MenuBuilder.cs: Replace $ with £ for product prices (line 60) and order totals (line 329)
- Fix ProductCarouselService.cs: Replace $ with £ in product captions and multi-buy offers (lines 317, 325)
- Fix CallbackHandler.cs: Replace $ with £ in order confirmation message (line 800)

### Payment Amount Display Bug
- Fix MessageFormatter.cs: Remove flawed crypto detection logic (< 1.0m check)
- Bug: Order for £700 in ETH displayed as "£1.66" instead of "1.66 ETH"
- Root cause: RequiredAmount is always stored as crypto amount, not fiat
- Solution: Always display RequiredAmount with crypto symbol
- Impact: Fixes display for XMR, DOGE, LTC, and large ETH amounts

## Security: Remove PGP Encryption Feature

### Critical Security Issue Resolved
- PGP "encryption" was only Base64 encoding - NOT real encryption
- Shipping addresses stored as easily decoded text
- False sense of security for users

### Changes Made
- Mark EncryptWithPGP method as [Obsolete] in PrivacyService.cs
- Remove PGP encryption logic from order creation (LittleShopService.cs)
- Mark PGP properties as [Obsolete] in UserSession.cs models
- Disable EnablePGPEncryption feature flag in appsettings.json
- Add comments explaining feature removal

### Recommendation
Implement proper PGP encryption using BouncyCastle in future, or keep removed.

## Testing Required
- Verify all prices display with £ symbol
- Verify crypto payments show correct amount format (e.g., "1.66000000 ETH")
- Verify no PGP options appear in UI
- Test order creation without PGP encryption

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
SysAdmin 2025-10-03 17:36:10 +01:00
parent 16ec41ccca
commit 32d80e4b54
8 changed files with 36 additions and 67 deletions

View File

@ -797,7 +797,7 @@ namespace TeleBot.Handlers
message.MessageId,
$"✅ *Order Created Successfully!*\n\n" +
$"Order ID: `{order.Id}`\n" +
$"Total: ${order.TotalAmount:F2}\n\n" +
$"Total: £{order.TotalAmount:F2}\n\n" +
"Select your preferred payment method:",
parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown,
replyMarkup: MenuBuilder.PaymentMethodMenu(currencies)

View File

@ -52,8 +52,14 @@ namespace TeleBot.Models
public bool UseEphemeralMode { get; set; } = true;
public bool UseTorOnly { get; set; } = false;
public bool DisableAnalytics { get; set; } = true;
// PGP encryption feature removed - was not properly implemented
[Obsolete("PGP feature removed - not properly implemented")]
public bool RequirePGP { get; set; } = false;
[Obsolete("PGP feature removed - not properly implemented")]
public string? PGPPublicKey { get; set; }
public bool EnableDisappearingMessages { get; set; } = true;
public int DisappearingMessageTTL { get; set; } = 30; // seconds
}
@ -68,7 +74,10 @@ namespace TeleBot.Models
public string? ShippingCountry { get; set; } = "United Kingdom";
public string? Notes { get; set; }
public string? SelectedCurrency { get; set; }
[Obsolete("PGP feature removed - not properly implemented")]
public bool UsePGPEncryption { get; set; }
public OrderFlowStep CurrentStep { get; set; } = OrderFlowStep.CollectingName;
}

View File

@ -200,26 +200,9 @@ namespace TeleBot.Services
_logger.LogInformation("Creating anonymous order with identity {Identity}", identityReference);
}
// Encrypt shipping info if PGP is enabled
string shippingData = $"{session.OrderFlow.ShippingName}\n" +
$"{session.OrderFlow.ShippingAddress}\n" +
$"{session.OrderFlow.ShippingCity}\n" +
$"{session.OrderFlow.ShippingPostCode}\n" +
$"{session.OrderFlow.ShippingCountry}";
if (session.Privacy.RequirePGP && !string.IsNullOrEmpty(session.Privacy.PGPPublicKey))
{
var encrypted = await _privacyService.EncryptWithPGP(shippingData, session.Privacy.PGPPublicKey);
if (encrypted != null)
{
// Store encrypted data in notes field
session.OrderFlow.Notes = $"PGP_ENCRYPTED_SHIPPING:\n{encrypted}";
session.OrderFlow.ShippingName = "PGP_ENCRYPTED";
session.OrderFlow.ShippingAddress = "PGP_ENCRYPTED";
session.OrderFlow.ShippingCity = "PGP_ENCRYPTED";
session.OrderFlow.ShippingPostCode = "PGP_ENCRYPTED";
}
}
// PGP encryption feature removed - was not properly implemented
// Shipping data is now stored in plain text (standard for e-commerce)
// For enhanced privacy, consider implementing proper encryption in future
var request = new CreateOrderRequest
{

View File

@ -60,21 +60,19 @@ namespace TeleBot.Services
return $"ANON-{reference}";
}
/// <summary>
/// ⚠️ REMOVED: PGP ENCRYPTION FEATURE HAS BEEN REMOVED ⚠️
/// This method was not properly implemented and provided a false sense of security.
/// It only performed Base64 encoding, not real encryption.
/// Feature removed to eliminate security vulnerability.
/// </summary>
[Obsolete("PGP encryption feature removed - was not properly implemented")]
public async Task<string?> EncryptWithPGP(string data, string publicKey)
{
try
{
// TODO: Implement PGP encryption when PgpCore API is stable
_logger.LogWarning("PGP encryption not implemented - returning base64 encoded data as placeholder");
_logger.LogWarning("⚠️ PGP encryption feature has been removed - returning null");
await Task.CompletedTask;
return Convert.ToBase64String(Encoding.UTF8.GetBytes($"PGP_PLACEHOLDER:{data}"));
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to encrypt with PGP");
return null;
}
}
public Task<HttpClient> CreateTorHttpClient()
{

View File

@ -314,7 +314,7 @@ namespace TeleBot.Services
private string FormatProductCaption(Product product)
{
var caption = $"🛍️ *{product.Name}*\n";
caption += $"💰 *${product.Price:F2}*\n";
caption += $"💰 *£{product.Price:F2}*\n";
// Show multi-buy deals if available
if (product.MultiBuys != null && product.MultiBuys.Any(mb => mb.IsActive))
@ -322,7 +322,7 @@ namespace TeleBot.Services
caption += "\n🏷 *Special Offers:*\n";
foreach (var multibuy in product.MultiBuys.Where(mb => mb.IsActive).OrderBy(mb => mb.Quantity))
{
caption += $" • {multibuy.Name}: ${multibuy.Price:F2} (${multibuy.PricePerUnit:F2} each)\n";
caption += $" • {multibuy.Name}: £{multibuy.Price:F2} (£{multibuy.PricePerUnit:F2} each)\n";
}
}

View File

@ -57,7 +57,7 @@ namespace TeleBot.UI
// Product buttons
foreach (var product in products.Items)
{
var price = $"${product.Price:F2}";
var price = $"£{product.Price:F2}";
buttons.Add(new[] {
InlineKeyboardButton.WithCallbackData(
$"{product.Name} - {price}",
@ -326,7 +326,7 @@ namespace TeleBot.UI
var status = GetOrderStatusEmoji(order.Status);
buttons.Add(new[] {
InlineKeyboardButton.WithCallbackData(
$"{status} Order {order.Id.ToString().Substring(0, 8)} - ${order.TotalAmount:F2}",
$"{status} Order {order.Id.ToString().Substring(0, 8)} - £{order.TotalAmount:F2}",
$"order:{order.Id}"
)
});

View File

@ -290,12 +290,8 @@ namespace TeleBot.UI
{
sb.AppendLine($" Address: `{payment.WalletAddress}`");
}
// Check if amount looks like a crypto amount (less than 1 for typical orders)
var isCryptoAmount = payment.RequiredAmount < 1.0m;
var amountDisplay = isCryptoAmount
? $"{payment.RequiredAmount:F8} {FormatCurrency(payment.Currency)}"
: $"£{payment.RequiredAmount:F2} (needs conversion to {FormatCurrency(payment.Currency)})";
sb.AppendLine($" Amount: {amountDisplay}");
// RequiredAmount is always stored as cryptocurrency amount
sb.AppendLine($" Amount: {payment.RequiredAmount:F8} {FormatCurrency(payment.Currency)}");
}
}
@ -308,30 +304,12 @@ namespace TeleBot.UI
sb.AppendLine($"💰 *Payment Instructions*\n");
sb.AppendLine($"*Currency:* {FormatCurrency(payment.Currency)}");
// Check if amount looks like a crypto amount (less than 1 for typical orders)
var isCryptoAmount = payment.RequiredAmount < 1.0m;
if (isCryptoAmount)
{
// RequiredAmount is always stored as cryptocurrency amount
sb.AppendLine($"*Amount:* `{payment.RequiredAmount:F8} {FormatCurrency(payment.Currency)}`");
}
else
{
// This looks like a GBP amount that needs conversion
sb.AppendLine($"*Order Total:* £{payment.RequiredAmount:F2}");
sb.AppendLine($"*Note:* Amount needs conversion to {FormatCurrency(payment.Currency)}");
sb.AppendLine($"*Please check payment link for actual crypto amount*");
}
sb.AppendLine($"*Status:* {FormatPaymentStatus(payment.Status)}");
sb.AppendLine($"*Expires:* {payment.ExpiresAt:yyyy-MM-dd HH:mm} UTC");
if (isCryptoAmount)
{
sb.AppendLine($"\n*Send exactly {payment.RequiredAmount:F8} {FormatCurrency(payment.Currency)} to:*");
}
else
{
sb.AppendLine($"\n*Wallet Address:*");
}
sb.AppendLine($"`{payment.WalletAddress}`");
if (!string.IsNullOrEmpty(payment.BTCPayCheckoutUrl))

View File

@ -39,7 +39,7 @@
"TorSocksPort": 9050,
"TorControlPort": 9051,
"OnionServiceDirectory": "/var/lib/tor/telebot/",
"Comment": "TOR is REQUIRED for location privacy. Ensure TOR service is running on port 9050"
"Comment": "TOR is REQUIRED for location privacy. PGP feature removed - not properly implemented."
},
"Redis": {
"ConnectionString": "localhost:6379",
@ -53,11 +53,12 @@
"Features": {
"EnableVoiceSearch": false,
"EnableQRCodes": true,
"EnablePGPEncryption": true,
"EnablePGPEncryption": false,
"EnableDisappearingMessages": true,
"EnableOrderMixing": true,
"MixingDelayMinSeconds": 60,
"MixingDelayMaxSeconds": 300
"MixingDelayMaxSeconds": 300,
"Comment": "PGP encryption feature removed - was not properly implemented"
},
"Logging": {
"LogLevel": {