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:
parent
16ec41ccca
commit
32d80e4b54
@ -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)
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
{
|
||||
|
||||
@ -60,20 +60,18 @@ 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");
|
||||
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;
|
||||
}
|
||||
_logger.LogWarning("⚠️ PGP encryption feature has been removed - returning null");
|
||||
await Task.CompletedTask;
|
||||
return null;
|
||||
}
|
||||
|
||||
public Task<HttpClient> CreateTorHttpClient()
|
||||
|
||||
@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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}"
|
||||
)
|
||||
});
|
||||
|
||||
@ -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)
|
||||
{
|
||||
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*");
|
||||
}
|
||||
// RequiredAmount is always stored as cryptocurrency amount
|
||||
sb.AppendLine($"*Amount:* `{payment.RequiredAmount:F8} {FormatCurrency(payment.Currency)}`");
|
||||
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($"\n*Send exactly {payment.RequiredAmount:F8} {FormatCurrency(payment.Currency)} to:*");
|
||||
sb.AppendLine($"`{payment.WalletAddress}`");
|
||||
|
||||
if (!string.IsNullOrEmpty(payment.BTCPayCheckoutUrl))
|
||||
|
||||
@ -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": {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user