diff --git a/api/logics.py b/api/logics.py index 97c921ca..f1d92e66 100644 --- a/api/logics.py +++ b/api/logics.py @@ -7,9 +7,10 @@ from api.models import Order, LNPayment, MarketTick, User, Currency from api.tasks import send_message from decouple import config +import gnupg + import math import ast -import time FEE = float(config("FEE")) MAKER_FEE_SPLIT = float(config("MAKER_FEE_SPLIT")) @@ -31,6 +32,7 @@ FIAT_EXCHANGE_DURATION = int(config("FIAT_EXCHANGE_DURATION")) class Logics: + @classmethod def validate_already_maker_or_taker(cls, user): """Validates if a use is already not part of an active order""" @@ -88,6 +90,44 @@ class Logics: return True, None, None + def validate_pgp_keys(pub_key, enc_priv_key): + ''' Validates PGP valid keys. Formats them in a way understandable by the frontend ''' + gpg = gnupg.GPG() + + # Uniform format as linux linebreaks. Windows users submitting their own keys have \r\n breaks. + enc_priv_key = enc_priv_key.replace('\r\n', '\n') + pub_key = pub_key.replace('\r\n', '\n') + + # Try to import and export the public key (without passphrase) + try: + import_pub_result = gpg.import_keys(pub_key) + pub_key = gpg.export_keys(import_pub_result.fingerprints[0]) + except: + return ( + False, + { + "bad_request": + "Your PGP public key does not seem valid" + }, + None, + None) + + # Try to import the encrypted private key (without passphrase) + try: + import_priv_result = gpg.import_keys(enc_priv_key) + except: + return ( + False, + { + "bad_request": + "Your PGP private key does not seem valid" + }, + None, + None) + + + return True, None, pub_key, enc_priv_key + @classmethod def validate_order_size(cls, order): """Validates if order size in Sats is within limits at t0""" diff --git a/api/models.py b/api/models.py index 53b8b8f7..39e776e1 100644 --- a/api/models.py +++ b/api/models.py @@ -425,15 +425,16 @@ def delete_lnpayment_at_order_deletion(sender, instance, **kwargs): class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) - # PGP keys, used for E2E chat encrytion. Priv key is encrypted with user's passphrase (highEntropyToken) + # PGP keys, used for E2E chat encryption. Priv key is encrypted with user's passphrase (highEntropyToken) public_key = models.TextField( - max_length=999, + # Actualy only 400-500 characters for ECC, but other types might be longer + max_length=2000, null=True, default=None, blank=True, ) encrypted_private_key = models.TextField( - max_length=999, + max_length=2000, null=True, default=None, blank=True, diff --git a/api/views.py b/api/views.py index 3b49a2ab..dcb51bd0 100644 --- a/api/views.py +++ b/api/views.py @@ -635,6 +635,10 @@ class UserView(APIView): encrypted_private_key = serializer.data.get("encrypted_private_key") ref_code = serializer.data.get("ref_code") + valid, bad_keys_context, public_key, encrypted_private_key = Logics.validate_pgp_keys(public_key, encrypted_private_key) + if not valid: + return Response(bad_keys_context, status.HTTP_400_BAD_REQUEST) + if not public_key or not encrypted_private_key: context["bad_request"] = "Must provide valid 'pub' and 'enc_priv' PGP keys" return Response(context, status.HTTP_400_BAD_REQUEST) diff --git a/docs/assets/images/misc/learn-robosats-home.jpg b/docs/assets/images/misc/learn-robosats-home.jpg deleted file mode 100644 index 76c9d1d8..00000000 Binary files a/docs/assets/images/misc/learn-robosats-home.jpg and /dev/null differ diff --git a/frontend/src/components/FlagWithProps/FlagWithProps.tsx b/frontend/src/components/FlagWithProps/FlagWithProps.tsx index 4043b5f7..899fa3a4 100644 --- a/frontend/src/components/FlagWithProps/FlagWithProps.tsx +++ b/frontend/src/components/FlagWithProps/FlagWithProps.tsx @@ -18,10 +18,12 @@ const FlagWithProps = ({ code }: Props): JSX.Element => { if(code === 'AUD') flag = ; if(code === 'ARS') flag = ; if(code === 'BRL') flag = ; + if(code === 'BYN') flag = ; if(code === 'CAD') flag = ; if(code === 'CHF') flag = ; if(code === 'CLP') flag = ; if(code === 'CNY') flag = ; + if(code === 'EGP') flag = ; if(code === 'EUR') flag = ; if(code === 'HRK') flag = ; if(code === 'CZK') flag = ; @@ -33,6 +35,8 @@ const FlagWithProps = ({ code }: Props): JSX.Element => { if(code === 'ISK') flag = ; if(code === 'JPY') flag = ; if(code === 'KRW') flag = ; + if(code === 'LKR') flag = ; + if(code === 'MAD') flag = ; if(code === 'MXN') flag = ; if(code === 'NOK') flag = ; if(code === 'NZD') flag = ; diff --git a/frontend/static/assets/currencies.json b/frontend/static/assets/currencies.json index 1adcbf99..01356b1f 100644 --- a/frontend/static/assets/currencies.json +++ b/frontend/static/assets/currencies.json @@ -14,7 +14,7 @@ "13":"SGD", "14":"NOK", "15":"MXN", - "16":"KRW", + "16":"BYN", "17":"RUB", "18":"ZAR", "19":"TRY", @@ -63,6 +63,9 @@ "62":"TZS", "63":"XAF", "64":"UAH", + "65":"EGP", + "66":"LKR", + "67":"MAD", "300":"XAU", "1000":"BTC" } diff --git a/requirements.txt b/requirements.txt index f90d3dbc..43fe469d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,8 +10,8 @@ djangorestframework==3.13.1 channels==3.0.4 channels-redis==3.3.1 celery==5.2.3 -googleapis-common-protos==1.53.0 grpcio==1.43.0 +googleapis-common-protos==1.53.0 grpcio-tools==1.43.0 numpy==1.22.2 Pillow==7.0.0 @@ -24,4 +24,5 @@ gunicorn==20.1.0 psycopg2==2.9.3 SQLAlchemy==1.4.31 django-import-export==2.7.1 -requests[socks] \ No newline at end of file +requests[socks] +python-gnupg==0.4.9 \ No newline at end of file